/**
 * 
 */
package idv.takeshi.software.productline.bookstore.infrastructure.persistence.jpa;

import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.commons.lang.Validate;
import org.springframework.stereotype.Repository;

import idv.takeshi.software.productline.bookstore.domain.model.useraccount.UserAccount;
import idv.takeshi.software.productline.bookstore.domain.model.useraccount.UserAccountDuplicateException;
import idv.takeshi.software.productline.bookstore.domain.model.useraccount.UserAccountRepository;

/**
 * A model repository implementation for UserAccountRepository.
 * @author takeshi
 *
 */
@Repository("userAccountRepository")
public class UserAccountRepositoryImpl implements UserAccountRepository {
	
	@PersistenceContext
	private EntityManager entityManager;

	/* (non-Javadoc)
	 * @see idv.takeshi.software.productline.bookstore.domain.model.useraccount.UserAccountRepository#add(idv.takeshi.software.productline.bookstore.domain.model.useraccount.UserAccount)
	 */
	public void add(UserAccount userAccount) throws UserAccountDuplicateException {
		Validate.notNull(userAccount, "userAccount shall always not be null");
		if(null != this.findByAccountName(userAccount.getAccountName())){
			throw new UserAccountDuplicateException("userAccount:" + userAccount.getAccountName() +
					" is duplicate");
		}
		this.entityManager.persist(userAccount);
	}

	/* (non-Javadoc)
	 * @see idv.takeshi.software.productline.bookstore.domain.model.useraccount.UserAccountRepository#find(java.lang.Long)
	 */
	public UserAccount findById(Long id) {
		Validate.notNull(id, "id shall always not be null");
		return this.entityManager.find(UserAccount.class, id);
	}

	/* (non-Javadoc)
	 * @see idv.takeshi.software.productline.bookstore.domain.model.useraccount.UserAccountRepository#remove(idv.takeshi.software.productline.bookstore.domain.model.useraccount.UserAccount)
	 */
	public void remove(UserAccount userAccount) {
		Validate.notNull(userAccount, "userAccount shall always not be null");
		this.entityManager.remove(userAccount);
	}

	/* (non-Javadoc)
	 * @see idv.takeshi.software.productline.bookstore.domain.model.useraccount.UserAccountRepository#findByActivationKey(java.lang.String)
	 */
	public UserAccount findByActivationKey(String activationKey) {
		Validate.notEmpty(activationKey, "activationKey shall always not be null/empty");
		UserAccount userAccount = null;
		Query query = this.entityManager.createNamedQuery("findByActivationKey");
		query.setParameter("key", activationKey);
		try{
			userAccount = (UserAccount) query.getSingleResult();
		} catch(NoResultException e){
			//DO NOTHING
		}
		return userAccount;
	}

	/* (non-Javadoc)
	 * @see idv.takeshi.software.productline.bookstore.domain.model.useraccount.UserAccountRepository#findByAccuntName(java.lang.String)
	 */
	public UserAccount findByAccountName(String accountName) {
		UserAccount userAccount = null;
		Validate.notEmpty(accountName, "accountName shall always not be null/empty");
		Query query = this.entityManager.createNamedQuery("findByAccountName");
		query.setParameter("accountName", accountName);
		try{
			userAccount = (UserAccount) query.getSingleResult();
		} catch(NoResultException e){
			//DO NOTHING
		}
		return userAccount;
	}

	/**
	 * @return the entityManager
	 */
	public EntityManager getEntityManager() {
		return entityManager;
	}

}
